package com.etung.iot.demo.storage;

import com.etung.iot.demo.dao.RealDataMapper;
import com.etung.iot.demo.modles.RealData;
import com.etung.iot.demo.modles.StorageEntity;
import com.etung.iot.demo.storage.constorage.TriggerConditionStoreRule;
import com.etung.iot.demo.utils.BigDecimalUtil;
import com.etung.iot.demo.utils.SpringContextUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.math.BigDecimal;
import java.util.regex.Pattern;

@Component
@Storage(StorageConstant.CONDITION_STORAGE)
public class ConditionStoreRule implements StorageHandler {
    @Autowired
    private StorageRuleUtil storageRuleUtil;
    @Autowired
    private RealDataMapper realDataMapper;
    @Autowired
    private ConStorageSelector conStorageSelector;


    @Override
    public void handler(RealData realData) {
        String imei = realData.getImei();
        int varId = realData.getVarId();
        StorageEntity storageRule = storageRuleUtil.getStorageRule(imei, varId);
        boolean isNeedSave = false;
        if (!StringUtils.isEmpty(storageRule.getConditionRule())) {
            isNeedSave = checkCondition(storageRule.getConditionRule(), realData);
        }
        if (isNeedSave) {
            realDataMapper.insert(realData);
        } else {
            conStorageSelector.saveConditionRealData(realData);
        }
    }

    private boolean checkCondition(String condition, RealData realData) {
        boolean res = false;
        //正则表达式校验合法性
        String pattern = "(^x(=|!=|<|<=|>|>=|)\\d+\\.?\\d*$)|(^\\d+(<|<=)x(<|<=)\\d+\\.?\\d*$)";
        boolean isMatch = Pattern.matches(pattern, condition);
        if (isMatch) {
            BigDecimal currentValue = BigDecimalUtil.getBigDecimal(realData.getValue());
            if (condition.startsWith("x")) {
                res = checkRightPart(condition, currentValue);
            } else {
                int index = condition.indexOf("x");
                String leftCondition = condition.substring(0, index + 1);
                String rightCondition = condition.substring(index);
                res = checkLeftPart(leftCondition, currentValue) && checkRightPart(rightCondition, currentValue);
            }
        }
        return res;
    }

    private boolean checkRightPart(String rightCondition, BigDecimal currentValue) {
        BigDecimal specifiedValue;
        String symbol;
        if (StringUtils.isNumeric(rightCondition.substring(2))) {
            specifiedValue = BigDecimalUtil.getBigDecimal(rightCondition.substring(2));
            symbol = rightCondition.substring(1, 2);
        } else {
            specifiedValue = BigDecimalUtil.getBigDecimal(rightCondition.substring(3));
            symbol = rightCondition.substring(1, 3);
        }
        return compare(symbol, currentValue, specifiedValue);
    }

    private boolean checkLeftPart(String leftCondition, BigDecimal currentValue) {
        int index = leftCondition.indexOf("x");
        BigDecimal specifiedValue;
        String symbol;
        if (StringUtils.isNumeric(leftCondition.substring(0, index - 1))) {
            specifiedValue = BigDecimalUtil.getBigDecimal(leftCondition.substring(0, index - 1));
            symbol = leftCondition.substring(index - 1, index);
        } else {
            specifiedValue = BigDecimalUtil.getBigDecimal(leftCondition.substring(0, index - 2));
            symbol = leftCondition.substring(index - 2, index);
        }
        return compare(symbol, specifiedValue, currentValue);
    }

    private boolean compare(String symbol, BigDecimal currentValue, BigDecimal ratedValue) {
        boolean res = false;
        switch (symbol) {
            case "=":
                if (currentValue.compareTo(ratedValue) == 0) {
                    res = true;
                }
                break;
            case "!=":
                if (currentValue.compareTo(ratedValue) != 0) {
                    res = true;
                }
                break;
            case "<":
                if (currentValue.compareTo(ratedValue) < 0) {
                    res = true;
                }
                break;
            case "<=":
                if (currentValue.compareTo(ratedValue) <= 0) {
                    res = true;
                }
                break;
            case ">":
                if (currentValue.compareTo(ratedValue) > 0) {
                    res = true;
                }
                break;
            case ">=":
                if (currentValue.compareTo(ratedValue) >= 0) {
                    res = true;
                }
                break;
        }
        return res;
    }
}
